home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / vbcc / pasm / directives.c next >
C/C++ Source or Header  |  1998-01-05  |  25KB  |  1,066 lines

  1. /* $VER: pasm directives.c V0.6 (30.10.97)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-97 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.6 (30.10.97) phx
  16.  *      The names of macros will be converted to lower case (otherwise,
  17.  *      they would remain inaccessible ;)
  18.  * v0.5 (12.10.97) phx
  19.  *      .set directive is allowed multiple times on the same symbol.
  20.  *      If a .set-assignment can't be resolved in pass 1, the symbol
  21.  *      is no longer undefined, but defined with an absolute default
  22.  *      value of '1'. So .ifdef will work correctly.
  23.  *      .globl directive declares unknown symbols in pass 1 as
  24.  *      externally defined. If the symbol is defined later in the
  25.  *      source, it will be made global by add_symbol()/tables.c.
  26.  * v0.4 (29.04.97) phx
  27.  *      .new_section sets type of section-symbol to SYMI_SECTION.
  28.  *      New directives: .baserel
  29.  * v0.3 (10.04.97) phx
  30.  *      Some vbcc-specific changes.
  31.  * v0.2 (25.03.97) phx
  32.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  33.  *      or ELF output format may be selected. ELF is default for all
  34.  *      currently supported platforms. PPCasm supports nine different
  35.  *      relocation types (there are much more...).
  36.  *      Compiles and works also under NetBSD/amiga (68k).
  37.  *      Changed function declaration to 'new style' in all sources
  38.  *      (to avoid problems with '...' for example).
  39.  *      Floating pointer support. New directives: .fail, .ident, .file,
  40.  *      .float, .ufloat, .double, .udouble, .local.
  41.  * v0.1 (11.03.97) phx
  42.  *      First test version with all PowerPC instructions and most
  43.  *      important directives. Only raw, absolute output.
  44.  *      .ident and .file directives are supported, but have no effect.
  45.  *      Especially floating point directives are missing.
  46.  * v0.0 (21.02.97) phx
  47.  *      File created.
  48.  */
  49.  
  50.  
  51. #define DIRECTIVES_C
  52. #include "ppcasm.h"
  53.  
  54.  
  55. void activate_section(struct GlobalVars *,struct Section *);
  56. void alignment(struct GlobalVars *,unsigned long);
  57. char escchar(char);
  58.  
  59. static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
  60. static char *section_attributes(struct GlobalVars *,char *,uint8 *,
  61.                                 uint8 *,uint8 *,uint8 *);
  62. static void _uahalf(struct GlobalVars *,struct ParsedLine *);
  63. static void _uaword(struct GlobalVars *,struct ParsedLine *);
  64. static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
  65. static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
  66. static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
  67.  
  68.  
  69.  
  70. static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
  71. {
  72.   start_section(gv,pl,1);
  73. }
  74.  
  75.  
  76. static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
  77. {
  78.   start_section(gv,pl,0);
  79. }
  80.  
  81.  
  82. static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
  83.                           bool force_new)
  84. /* define a new section with new attributes or reactivate a */
  85. /* previously defined one */
  86. {
  87.   struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
  88.   struct Symbol *sym;
  89.   char *s,*name;
  90.   uint8 type,flags,protection,alignment;
  91.  
  92.   s = getarg(gv,pl->operand);  /* section's name */
  93.   name = remquotes(gv->strbuf);
  94.  
  95.   while (nexts = (struct Section *)sec->n.next) {
  96.     if (!strcmp(name,sec->name)) {
  97.  
  98.       if (force_new) {  /* overwrite an old section with the same name? */
  99.         sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
  100.         name = sec->name;
  101.         sec->name = allocstring(gv->strbuf);
  102.         break;
  103.       }
  104.  
  105.       else {  /* reactivate old section with the same name */
  106.         s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
  107.         if (type != ST_UNDEFINED)  /* attributes specified? */
  108.           if (sec->type!=type || sec->flags!=flags ||
  109.               sec->protection!=protection || sec->alignment!=alignment)
  110.             error(16);  /* section attributes don't match */
  111.         pl->type = OT_SECTION;
  112.         pl->opcode = (void *)sec;
  113.         activate_section(gv,sec);
  114.         checkEOL(s);
  115.         return;
  116.       }
  117.  
  118.     }
  119.     sec = nexts;
  120.   }
  121.  
  122.   /* create a new section */
  123.   sec = alloczero(sizeof(struct Section));
  124.   sec->name = allocstring(name);
  125.   s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
  126.                          &sec->alignment);
  127.   if (sec->type == ST_UNDEFINED) {  /* set default attributes */
  128.     sec->type = ST_DATA;
  129.     sec->protection = SP_READ|SP_WRITE;
  130.     sec->alignment = 2;
  131.   }
  132.   initlist(&sec->reloclist);
  133.   initlist(&sec->xreflist);
  134.   addtail(&gv->sectionlist,&sec->n);
  135.   pl->type = OT_SECTION;
  136.   pl->opcode = (void *)sec;
  137.   activate_section(gv,sec);
  138.   sym = add_symbol(gv,sec->name,SYM_RELOC,0);
  139.   sym->info = SYMI_SECTION;
  140.   checkEOL(s);
  141. }
  142.  
  143.  
  144. void activate_section(struct GlobalVars *gv,struct Section *sec)
  145. {
  146.   gv->csect = sec;  /* set active section */
  147.   gv->lcsym->relsect = sec;
  148.   gv->lcsym->value = sec->pc;
  149. }
  150.  
  151.  
  152. static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
  153.                                 uint8 *f,uint8 *p,uint8 *a)
  154. /* fill in section attributes, if specified */
  155. {
  156.   char c,*attr;
  157.  
  158.   *t = ST_UNDEFINED;
  159.   *f = *p = *a = 0;
  160.   s = skipspaces(s);
  161.   if (*s) {
  162.     if (*s == ',') {
  163.       s = skipspaces(++s);
  164.       s = getarg(gv,s);
  165.       c = *gv->strbuf;
  166.       if (c=='\"' || c=='\'') {
  167.         attr = remquotes(gv->strbuf);
  168.         while (c = *attr++) {
  169.           switch (c) {
  170.             /* contents type */
  171.             case 'c':
  172.               *t = ST_CODE;
  173.               break;
  174.             case 'd':
  175.               *t = ST_DATA;
  176.               break;
  177.             case 'u':
  178.               *t = ST_UDATA;
  179.               *f |= SF_UNINITIALIZED;
  180.               break;
  181.             case 'i':
  182.               *t = ST_STRUCT;
  183.               *f |= SF_DISCARD|SF_UNINITIALIZED;
  184.               break;
  185.             /* protection */
  186.             case 'r':
  187.               *p |= SP_READ;
  188.               break;
  189.             case 'w':
  190.               *p |= SP_WRITE;
  191.               break;
  192.             case 'x':
  193.               *p |= SP_EXEC;
  194.               break;
  195.             case 's':
  196.               *p |= SP_SHARE;
  197.               break;
  198.             case 'n': /* remove and discard currently not supported */
  199.             case 'R':
  200.               break;
  201.             default:
  202.               if (c>='0' && c <='6')
  203.                 *a = (uint8)(c-'0');  /* alignment */
  204.               else
  205.                 error(15,c);  /* illegal section attribute */
  206.               break;
  207.           }
  208.         }
  209.       }
  210.       else
  211.         error(14);  /* string constant expected */
  212.     }
  213.     else if (*s != '#')
  214.       error(12);  /* colon expected */
  215.   }
  216.   return (s);
  217. }
  218.  
  219.  
  220. static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
  221. {
  222.   char *s = getsymbol(gv,pl->operand);
  223.   struct Expression exp;
  224.   struct Section *cs;
  225.   char setname[STRBUFSIZE];
  226.   struct Symbol *sym;
  227.  
  228.   if (*gv->strbuf) {
  229.     strcpy(setname,gv->strbuf);
  230.     if (s = check_comma(s)) {
  231.       s = eval_expression(gv,&exp,s);
  232.       if (exp.type != SYM_UNDEF) {
  233.         if (exp.type != SYM_EXTERN) {
  234.           if (exp.type == SYM_RELOC) {
  235.             if (exp.reloctype == R_PPC_ADDR32) {
  236.               if (sym = search_symbol(gv,setname)) {
  237.                 sym->value = exp.value;
  238.                 sym->type = SYM_RELOC;
  239.                 sym->relsect = exp.symbol->relsect;
  240.               }
  241.               else {
  242.                 cs = gv->csect;
  243.                 gv->csect = exp.symbol->relsect;
  244.                 add_symbol(gv,setname,SYM_RELOC,exp.value);
  245.                 gv->csect = cs;
  246.               }
  247.             }
  248.             else
  249.               error(29);  /* can't assign relocatable half word */
  250.           }
  251.           else {
  252.             if (sym = search_symbol(gv,setname)) {
  253.               sym->value = exp.value;
  254.               sym->type = SYM_ABS;
  255.             }
  256.             else
  257.               add_symbol(gv,setname,SYM_ABS,exp.value);
  258.           }
  259.         }
  260.         else
  261.           error(28);  /* can't assign external symbol */
  262.       }
  263.       else {
  264.         if (gv->pass)  /* expression still undefined in pass 2 ? */
  265.           error(19);  /* undefined symbol */
  266.         else if (!search_symbol(gv,setname))
  267.           /* set value to 1 if unknown in first pass */
  268.           add_symbol(gv,setname,SYM_ABS,1);
  269.       }
  270.       checkEOL(s);
  271.       return;
  272.     }
  273.   }
  274.   else
  275.     error(17);  /* missing argument */
  276. }
  277.  
  278.  
  279. static void _macro(struct GlobalVars *gv,struct ParsedLine *pl)
  280. {
  281.   struct Macro *mac = alloczero(sizeof(struct Macro));
  282.   char *s = getsymbol(gv,pl->operand);
  283.  
  284.   mac->name = allocstring(gv->strbuf);
  285.   lower_case(mac->name);  /* convert macro name to lower case */
  286.   mac->text = gv->cthread->srcptr;
  287.   mac->nlines = gv->absline + 1;
  288.   gv->cthread->macskip = mac;
  289.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  290.   checkEOL(s);
  291. }
  292.  
  293.  
  294. static void _include(struct GlobalVars *gv,struct ParsedLine *pl)
  295. {
  296.   char *s;
  297.  
  298.   if (!gv->pass) {  /* pass 1 */
  299.     s = getarg(gv,pl->operand);  /* include file's name */
  300.  
  301.     /* recursively call pass 1 and create new SourceThread */
  302.     pass1(gv,include_source(gv,remquotes(gv->strbuf)),NULL,gv->cthread);
  303.     checkEOL(s);
  304.   }
  305.  
  306.   else  /* recursively call pass 2 */
  307.     pass2(gv,get_source(gv),NULL,gv->cthread);
  308. }
  309.  
  310.  
  311. void alignment(struct GlobalVars *gv,unsigned long a)
  312. {
  313.   unsigned long x = (1<<a) - 1;
  314.   unsigned long pc = gv->csect->pc;
  315.  
  316.   pc = (pc + x) & ~x;
  317.   if (!gv->pass)
  318.     gv->csect->pc = pc;
  319.   else
  320.     store_space(gv,pc - gv->csect->pc);
  321. }
  322.  
  323.  
  324. static void _align(struct GlobalVars *gv,struct ParsedLine *pl)
  325. {
  326.   char *s;
  327.   uint32 a=2;
  328.   static uint8 na=0;
  329.  
  330.   if (pl->flags & PLF_ALIGN) {
  331.     if (++na > 2)
  332.       gv->vc = TRUE;
  333.   }
  334.   else
  335.     na = 0;
  336.   s = getintexp(gv,pl->operand,&a);
  337.   alignment(gv,a);
  338.   gv->alignflag = TRUE;
  339.   if (!gv->pass)
  340.     checkEOL(s);
  341. }
  342.  
  343.  
  344. static void _space(struct GlobalVars *gv,struct ParsedLine *pl)
  345. {
  346.   char *s;
  347.   uint32 n=0;
  348.  
  349.   s = getintexp(gv,pl->operand,&n);
  350.   if (!gv->pass) {
  351.     pcadd(gv,n);
  352.     checkEOL(s);
  353.   }
  354.   else
  355.     store_space(gv,n);
  356. }
  357.  
  358.  
  359. char escchar(char c)
  360. /* convert escape code */
  361. {
  362.   switch (c) {
  363.     case 'b':
  364.       c = 8;
  365.       break;
  366.     case 'f':
  367.       c = 12;
  368.       break;
  369.     case 'n':
  370.       c = 10;
  371.       break;
  372.     case 'r':
  373.       c = 13;
  374.       break;
  375.     case 't':
  376.       c = 8;
  377.       break;
  378.   }
  379.   return (c);
  380. }
  381.  
  382.  
  383. static void _byte(struct GlobalVars *gv,struct ParsedLine *pl)
  384. {
  385.   char *s = pl->operand;
  386.   char *sb,c;
  387.   uint8 pass = gv->pass;
  388.   uint32 i;
  389.  
  390.   for (;;) {
  391.     if ((c = *s) == '\"') {  /* read string */
  392.       s = getarg(gv,s);
  393.       sb = remquotes(gv->strbuf);
  394.       if (!pass)
  395.         while (c = *sb++) {
  396.           if (c=='\\' || c=='\"')
  397.             if (*sb++ == 0)
  398.               break;
  399.           pcadd(gv,1);
  400.         }
  401.       else
  402.         while (c = *sb++) {
  403.           if (c == '\\') {
  404.             if (!(c = escchar(*sb++)))
  405.               break;
  406.           }
  407.           else if (c == '\"') {
  408.             if (!(c = *sb++))
  409.               break;
  410.           }
  411.           store_byte(gv,(uint8)c);
  412.         }
  413.     }
  414.  
  415.     else {  /* get integer expression */
  416.       if (c==0 || c=='#') {
  417.         error(17);  /* missing argument */
  418.         break;
  419.       }
  420.       if (!pass) {
  421.         s = skipexpression(gv,s);
  422.         pcadd(gv,1);
  423.       }
  424.       else {
  425.         s = getintexp(gv,s,&i);
  426.         store_byte(gv,(uint8)i);
  427.         s = skipspaces(s);
  428.       }
  429.     }
  430.  
  431.     c = *s++;
  432.     if (c==0 || c=='#')  /* no more arguments? */
  433.       break;
  434.     if (c != ',') {
  435.       error(12);  /* colon expected */
  436.       break;
  437.     }
  438.     s = skipspaces(s);
  439.   }
  440. }
  441.  
  442.  
  443. static void _string(struct GlobalVars *gv,struct ParsedLine *pl)
  444. {
  445.   char *s = pl->operand;
  446.   char *sb,c;
  447.   uint8 pass = gv->pass;
  448.  
  449.   for (;;) {
  450.     if ((c = *s) == '\"') {  /* read string */
  451.       s = getarg(gv,s);
  452.       sb = remquotes(gv->strbuf);
  453.       if (!pass) {
  454.         while (c = *sb++) {
  455.           if (c=='\\' || c=='\"')
  456.             if (*sb++ == 0)
  457.               break;
  458.           pcadd(gv,1);
  459.         }
  460.         pcadd(gv,1);
  461.       }
  462.       else {
  463.         while (c = *sb++) {
  464.           if (c == '\\') {
  465.             if (!(c = escchar(*sb++)))
  466.               break;
  467.           }
  468.           else if (c == '\"') {
  469.             if (!(c = *sb++))
  470.               break;
  471.           }
  472.           store_byte(gv,(uint8)c);
  473.         }
  474.         store_byte(gv,0);
  475.       }
  476.     }
  477.     else {
  478.       error(14);  /* string constant expected */
  479.       break;
  480.     }
  481.  
  482.     c = *s++;
  483.     if (c==0 || c=='#')  /* no more arguments? */
  484.       break;
  485.     if (c != ',') {
  486.       error(12);  /* colon expected */
  487.       break;
  488.     }
  489.     s = skipspaces(s);
  490.   }
  491. }
  492.  
  493.  
  494. static void _half(struct GlobalVars *gv,struct ParsedLine *pl)
  495. {
  496.   alignment(gv,1);
  497.   _uahalf(gv,pl);
  498. }
  499.  
  500.  
  501. static void _uahalf(struct GlobalVars *gv,struct ParsedLine *pl)
  502. {
  503.   char *s = pl->operand;
  504.   char *sb,c;
  505.   uint8 pass = gv->pass;
  506.   uint32 i;
  507.  
  508.   for (;;) {
  509.     c = *s;
  510.     if (c==0 || c=='#') {
  511.       error(17);  /* missing argument */
  512.       break;
  513.     }
  514.     if (!pass) {
  515.       s = skipexpression(gv,s);
  516.       pcadd(gv,2);
  517.     }
  518.     else {
  519.       s = getexp(gv,s,&i,2);
  520.       store_half(gv,(uint16)i);
  521.       s = skipspaces(s);
  522.     }
  523.  
  524.     c = *s++;
  525.     if (c==0 || c=='#')  /* no more arguments? */
  526.       break;
  527.     if (c != ',') {
  528.       error(12);  /* colon expected */
  529.       break;
  530.     }
  531.     s = skipspaces(s);
  532.   }
  533. }
  534.  
  535.  
  536. static void _word(struct GlobalVars *gv,struct ParsedLine *pl)
  537. {
  538.   alignment(gv,2);
  539.   _uaword(gv,pl);
  540. }
  541.  
  542.  
  543. static void _uaword(struct GlobalVars *gv,struct ParsedLine *pl)
  544. {
  545.   char *s = pl->operand;
  546.   char *sb,c;
  547.   uint8 pass = gv->pass;
  548.   uint32 i;
  549.  
  550.   for (;;) {
  551.     c = *s;
  552.     if (c==0 || c=='#') {
  553.       error(17);  /* missing argument */
  554.       break;
  555.     }
  556.     if (!pass) {
  557.       s = skipexpression(gv,s);
  558.       pcadd(gv,4);
  559.     }
  560.     else {
  561.       s = getexp(gv,s,&i,4);
  562.       store_word(gv,i);
  563.       s = skipspaces(s);
  564.     }
  565.  
  566.     c = *s++;
  567.     if (c==0 || c=='#')  /* no more arguments? */
  568.       break;
  569.     if (c != ',') {
  570.       error(12);  /* colon expected */
  571.       break;
  572.     }
  573.     s = skipspaces(s);
  574.   }
  575. }
  576.  
  577.  
  578. static void _float(struct GlobalVars *gv,struct ParsedLine *pl)
  579. {
  580.   alignment(gv,2);
  581.   uafloat(gv,pl,FALSE);
  582. }
  583.  
  584.  
  585. static void _uafloat(struct GlobalVars *gv,struct ParsedLine *pl)
  586. {
  587.   uafloat(gv,pl,FALSE);
  588. }
  589.  
  590.  
  591. static void _double(struct GlobalVars *gv,struct ParsedLine *pl)
  592. {
  593.   alignment(gv,3);
  594.   uafloat(gv,pl,TRUE);
  595. }
  596.  
  597.  
  598. static void _uadouble(struct GlobalVars *gv,struct ParsedLine *pl)
  599. {
  600.   uafloat(gv,pl,TRUE);
  601. }
  602.  
  603.  
  604. static void uafloat(struct GlobalVars *gv,struct ParsedLine *pl,bool dbl)
  605. {
  606.   char *s = pl->operand;
  607.   char *sb,c;
  608.   uint8 pass = gv->pass;
  609.   double f;
  610.  
  611.   for (;;) {
  612.     c = *s;
  613.     if (c==0 || c=='#') {
  614.       error(17);  /* missing argument */
  615.       break;
  616.     }
  617.     if (!pass) {
  618.       s = skipexpression(gv,s);
  619.       pcadd(gv,dbl?8:4);
  620.     }
  621.     else {
  622.       sscanf(s,"%lf",&f);
  623.       if (dbl)
  624.         store_double(gv,f);
  625.       else
  626.         store_float(gv,f);
  627.       s = skipexpression(gv,s);
  628.     }
  629.  
  630.     c = *s++;
  631.     if (c==0 || c=='#')  /* no more arguments? */
  632.       break;
  633.     if (c != ',') {
  634.       error(12);  /* colon expected */
  635.       break;
  636.     }
  637.     s = skipspaces(s);
  638.   }
  639. }
  640.  
  641.  
  642. static void _globl(struct GlobalVars *gv,struct ParsedLine *pl)
  643. {
  644.   char *s;
  645.   struct Symbol *sym;
  646.  
  647.   s = getsymbol(gv,pl->operand);
  648.   if (*gv->strbuf) {
  649.     if (!(sym = search_symbol(gv,gv->strbuf))) {
  650.       /* unknown in pass 1, then declare as externally defined first */
  651.       sym = add_symbol(gv,gv->strbuf,SYM_EXTERN,0);
  652.     }
  653.     sym->bind = SYMB_GLOBAL;
  654.     checkEOL(s);
  655.   }
  656.   else
  657.     error(17);  /* missing argument */
  658.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  659. }
  660.  
  661.  
  662. static void _local(struct GlobalVars *gv,struct ParsedLine *pl)
  663. {
  664.   char *s;
  665.   struct Symbol *sym;
  666.  
  667.   if (gv->pass) {
  668.     s = getsymbol(gv,pl->operand);
  669.     if (*gv->strbuf) {
  670.       if (!(sym = search_symbol(gv,gv->strbuf)))
  671.         error(19);  /* undefined symbol */
  672.       else
  673.         sym->bind = SYMB_LOCAL;
  674.       checkEOL(s);
  675.     }
  676.     else
  677.       error(17);  /* missing argument */
  678.   }
  679. }
  680.  
  681.  
  682. static void _bss(struct GlobalVars *gv,struct ParsedLine *pl)
  683. {
  684.   static char *bssname=".bss";
  685.   char *s;
  686.   struct Section *bss,*old=gv->csect;
  687.   uint32 size,align;
  688.   char symbname[STRBUFSIZE];
  689.   struct Symbol *sym;
  690.  
  691.   s = getsymbol(gv,pl->operand);
  692.   if (*gv->strbuf) {
  693.     if (!gv->pass)
  694.       strcpy(symbname,gv->strbuf);
  695.     if (!(s = check_comma(s)))
  696.       return;
  697.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  698.     align = (size>=8)? 3 : 2;
  699.     s = skipspaces(s);
  700.     if (*s == ',') {
  701.       s = getintexp(gv,++s,&align);  /* optional aligment */
  702.       if (align < 2)
  703.         align = 2;
  704.     }
  705.     if (bss = search_section(gv,bssname)) {
  706.       activate_section(gv,bss);
  707.       alignment(gv,align);
  708.       if (!gv->pass) {
  709.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  710.         sym->info = SYMI_OBJECT;
  711.         sym->size = size;
  712.         sym->bind = SYMB_LOCAL;
  713.         pcadd(gv,size);
  714.         checkEOL(s);
  715.       }
  716.       else
  717.         store_space(gv,size);
  718.       activate_section(gv,old);
  719.     }
  720.     else
  721.       error(47,bssname);  /* section .bss was never defined */
  722.   }
  723.   else
  724.     error(17);  /* missing argument */
  725. }
  726.  
  727.  
  728. static void _comm(struct GlobalVars *gv,struct ParsedLine *pl)
  729. {
  730.   static char *bssname=".bss";
  731.   char *s;
  732.   struct Section *bss,*old=gv->csect;
  733.   uint32 size;
  734.   char symbname[STRBUFSIZE];
  735.   struct Symbol *sym;
  736.  
  737.   s = getsymbol(gv,pl->operand);
  738.   if (*gv->strbuf) {
  739.     if (!gv->pass)
  740.       strcpy(symbname,gv->strbuf);
  741.     if (!(s = check_comma(s)))
  742.       return;
  743.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  744.     if (bss = search_section(gv,bssname)) {
  745.       activate_section(gv,bss);
  746.       alignment(gv,(size>=8)? 3:2);
  747.       if (!gv->pass) {
  748.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  749.         sym->info = SYMI_OBJECT;
  750.         sym->size = size;
  751.         sym->bind = SYMB_GLOBAL;  /* or SYMB_WEAK ?? */
  752.         pcadd(gv,size);
  753.         checkEOL(s);
  754.       }
  755.       else
  756.         store_space(gv,size);
  757.       activate_section(gv,old);
  758.     }
  759.     else
  760.       error(47,bssname);  /* section .bss was never defined */
  761.   }
  762.   else
  763.     error(17);  /* missing argument */
  764. }
  765.  
  766.  
  767. static void _type(struct GlobalVars *gv,struct ParsedLine *pl)
  768. {
  769.   char *s;
  770.   struct Symbol *sym;
  771.   uint32 type;
  772.  
  773.   if (gv->pass) {
  774.     s = getsymbol(gv,pl->operand);
  775.     if (*gv->strbuf) {
  776.       if (sym = search_symbol(gv,gv->strbuf)) {
  777.         if (s = check_comma(s)) {
  778.           s = getintexp(gv,s,&type);
  779.           sym->info = (uint8)type;
  780.           checkEOL(s);
  781.         }
  782.       }
  783.       else
  784.         error(19);  /* undefined symbol */
  785.     }
  786.     else
  787.       error(17);  /* missing argument */
  788.   }
  789. }
  790.  
  791.  
  792. static void _size(struct GlobalVars *gv,struct ParsedLine *pl)
  793. {
  794.   char *s;
  795.   struct Symbol *sym;
  796.   uint32 size;
  797.  
  798.   if (gv->pass) {
  799.     s = getsymbol(gv,pl->operand);
  800.     if (*gv->strbuf) {
  801.       if (sym = search_symbol(gv,gv->strbuf)) {
  802.         if (s = check_comma(s)) {
  803.           s = getintexp(gv,s,&size);
  804.           sym->size = size;
  805.           checkEOL(s);
  806.         }
  807.       }
  808.       else
  809.         error(19);  /* undefined symbol */
  810.     }
  811.     else
  812.       error(17);  /* missing argument */
  813.   }
  814. }
  815.  
  816.  
  817. static void _ifeq(struct GlobalVars *gv,struct ParsedLine *pl)
  818. {
  819.   ifeqs(gv,pl,0);
  820. }
  821.  
  822.  
  823. static void _ifne(struct GlobalVars *gv,struct ParsedLine *pl)
  824. {
  825.   ifeqs(gv,pl,1);
  826. }
  827.  
  828.  
  829. static void _ifgt(struct GlobalVars *gv,struct ParsedLine *pl)
  830. {
  831.   ifeqs(gv,pl,2);
  832. }
  833.  
  834.  
  835. static void _ifge(struct GlobalVars *gv,struct ParsedLine *pl)
  836. {
  837.   ifeqs(gv,pl,3);
  838. }
  839.  
  840.  
  841. static void _iflt(struct GlobalVars *gv,struct ParsedLine *pl)
  842. {
  843.   ifeqs(gv,pl,4);
  844. }
  845.  
  846.  
  847. static void _ifle(struct GlobalVars *gv,struct ParsedLine *pl)
  848. {
  849.   ifeqs(gv,pl,5);
  850. }
  851.  
  852.  
  853. static void ifeqs(struct GlobalVars *gv,struct ParsedLine *pl,int cond)
  854. {
  855.   char *s;
  856.   int32 val;
  857.   bool *condptr;
  858.  
  859.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  860.     condptr = &gv->ifcond[++gv->iflevel];
  861.     *condptr = FALSE;
  862.     s = getintexp(gv,pl->operand,&val);
  863.     switch (cond) {
  864.       case 0: /* eq */
  865.         if (val==0)
  866.           *condptr = TRUE;
  867.         break;
  868.       case 1: /* ne */
  869.         if (val!=0)
  870.           *condptr = TRUE;
  871.         break;
  872.       case 2: /* gt */
  873.         if (val>0)
  874.           *condptr = TRUE;
  875.         break;
  876.       case 3: /* ge */
  877.         if (val>=0)
  878.           *condptr = TRUE;
  879.         break;
  880.       case 4: /* lt */
  881.         if (val<0)
  882.           *condptr = TRUE;
  883.         break;
  884.       case 5: /* le */
  885.         if (val<=0)
  886.           *condptr = TRUE;
  887.         break;
  888.     }
  889.     checkEOL(s);
  890.   }
  891.   else
  892.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  893.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  894. }
  895.  
  896.  
  897. static void _ifdef(struct GlobalVars *gv,struct ParsedLine *pl)
  898. {
  899.   ifdef(gv,pl,TRUE);
  900. }
  901.  
  902.  
  903. static void _ifndef(struct GlobalVars *gv,struct ParsedLine *pl)
  904. {
  905.   ifdef(gv,pl,FALSE);
  906. }
  907.  
  908.  
  909. static void ifdef(struct GlobalVars *gv,struct ParsedLine *pl,bool c)
  910. {
  911.   char *s;
  912.   bool *condptr;
  913.  
  914.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  915.     condptr = &gv->ifcond[++gv->iflevel];
  916.     *condptr = c ? FALSE:TRUE;
  917.     s = getsymbol(gv,pl->operand);
  918.     if (*gv->strbuf)
  919.       if (search_symbol(gv,gv->strbuf))
  920.         *condptr = c;
  921.     checkEOL(s);
  922.   }
  923.   else
  924.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  925.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  926. }
  927.  
  928.  
  929. static void _else(struct GlobalVars *gv,struct ParsedLine *pl)
  930. {
  931.   if (gv->iflevel > 0) {
  932.     gv->ifcond[gv->iflevel] = FALSE;
  933.     checkEOL(pl->operand);
  934.   }
  935.   else
  936.     error(44,".else");  /* .else without matching .if */
  937.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  938. }
  939.  
  940.  
  941. static void _endif(struct GlobalVars *gv,struct ParsedLine *pl)
  942. {
  943.   if (gv->iflevel > 0) {
  944.     gv->iflevel--;
  945.     checkEOL(pl->operand);
  946.   }
  947.   else
  948.     error(44,".endif");  /* .endif without matching .if */
  949.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  950. }
  951.  
  952.  
  953. static void _fail(struct GlobalVars *gv,struct ParsedLine *pl)
  954. {
  955.   error(45);  /* fail directive encountered */
  956. }
  957.  
  958.  
  959. static void _noop(struct GlobalVars *gv,struct ParsedLine *pl)
  960. {
  961. }
  962.  
  963.  
  964. static void _ident(struct GlobalVars *gv,struct ParsedLine *pl)
  965. {
  966.   char *s = getarg(gv,pl->operand);  /* identification / comment */
  967.  
  968.   gv->ident = allocstring(remquotes(gv->strbuf));
  969.   checkEOL(s);
  970.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  971. }
  972.  
  973.  
  974. static void _file(struct GlobalVars *gv,struct ParsedLine *pl)
  975. {
  976.   char *s = getarg(gv,pl->operand);  /* source file name */
  977.  
  978.   gv->file = allocstring(remquotes(gv->strbuf));
  979.   checkEOL(s);
  980.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  981. }
  982.  
  983.  
  984. static void _baserel(struct GlobalVars *gv,struct ParsedLine *pl)
  985. {
  986.   char *s;
  987.   struct Symbol *sym;
  988.   uint32 tocreg;
  989.  
  990.   if (gv->pass) {
  991.     s = getsymbol(gv,pl->operand);
  992.     if (*gv->strbuf) {
  993.       if (sym = search_symbol(gv,gv->strbuf)) {
  994.         if (s = check_comma(s)) {
  995.           s = getintexp(gv,s,&tocreg);
  996.           if (sym->info == SYMI_SECTION) {
  997.             /* activate new base relative addressing mode */
  998.             gv->tocsect = sym->relsect;
  999.             gv->rtoc = (int)tocreg;
  1000.           }
  1001.           else
  1002.             error(50,sym->name);  /* symbol is not a section base address */
  1003.           checkEOL(s);
  1004.         }
  1005.       }
  1006.       else
  1007.         error(19);  /* undefined symbol */
  1008.     }
  1009.     else
  1010.       error(17);  /* missing argument */
  1011.   }
  1012. }
  1013.  
  1014.  
  1015.  
  1016. struct Directive directives[] = {
  1017.   0,".new_section",_new_section,
  1018.   0,".section",_section,
  1019.   0,".set",_set,
  1020.   0,".macro",_macro,
  1021.   0,".include",_include,
  1022.   0,".align",_align,
  1023.   0,".space",_space,
  1024.   0,".byte",_byte,
  1025.   0,".ascii",_byte,
  1026.   0,".string",_string,
  1027.   0,".asciiz",_string,
  1028.   0,".half",_half,
  1029.   0,".short",_half,
  1030.   0,".word",_word,
  1031.   0,".long",_word,
  1032.   0,".float",_float,
  1033.   0,".double",_double,
  1034.   0,".uahalf",_uahalf,
  1035.   0,".uashort",_uahalf,
  1036.   0,".uaword",_uaword,
  1037.   0,".ualong",_uaword,
  1038.   0,".uafloat",_uafloat,
  1039.   0,".uadouble",_uadouble,
  1040.   0,".globl",_globl,
  1041.   0,".global",_globl,
  1042.   0,".extern",_globl,
  1043.   0,".local",_local,
  1044.   0,".bss",_bss,
  1045.   0,".lcomm",_bss,
  1046.   0,".comm",_comm,
  1047.   0,".type",_type,
  1048.   0,".size",_size,
  1049.   0,".if",_ifne,
  1050.   0,".ifeq",_ifeq,
  1051.   0,".ifne",_ifne,
  1052.   0,".ifgt",_ifgt,
  1053.   0,".ifge",_ifge,
  1054.   0,".iflt",_iflt,
  1055.   0,".ifle",_ifle,
  1056.   0,".ifdef",_ifdef,
  1057.   0,".ifndef",_ifndef,
  1058.   0,".else",_else,
  1059.   0,".endif",_endif,
  1060.   0,".fail",_fail,
  1061.   0,".ident",_ident,
  1062.   0,".file",_file,
  1063.   0,".baserel",_baserel,
  1064.   0,0 /* end mark */
  1065. };
  1066.